/**
 * Game类       整个游戏类
 * @map         地图实例化对象
 * @snake       蛇类实例化对象
 * @food        食物实例化对象
 * @block       障碍物实例化对象
 * 
 **/
function Game(map, snake, food, block) {
    // 接收数据
    this.map = map;
    this.snake = snake;
    this.food = food;
    this.block = block;
    // 定义定时器句柄
    this.timer = null;
    // 定义标记
    this.flag = null;


    // 执行init方法
    this.init();
}

// 定义初始化方法
Game.prototype.init = function() {
    // 执行渲染地图方法
    this.renderMap();
    // 执行渲染食物方法
    this.renderFood();
    // 执行渲染蛇的方法
    this.renderSnake();
    // 渲染障碍物
    this.renderBlock();
    // 执行绑定事件方法
    this.bindEvent();
    // 游戏开始
    this.start();
}

// 定义渲染地图的方法
Game.prototype.renderMap = function() {
    // 执行map中的fill
    this.map.fill();
}

// 渲染食物
Game.prototype.renderFood = function() {
    // 所谓渲染食物 就是找到map中某一个行容器的某一个列span元素即可
    // 获取食物的坐标
    var x = this.food.x;
    var y = this.food.y;

    // 更换背景图片
    this.map.arr[x][y].style.backgroundImage = 'url('+ this.food.img_url +')';
}

// 渲染蛇
Game.prototype.renderSnake = function() {
    // 获取蛇的头部
    var head = this.snake.arr[this.snake.arr.length - 1];
    // 渲染头部图片
    this.map.arr[head.x][head.y].style.backgroundImage = 'url('+ this.snake.head_img[this.snake.head_idx]  +')';


    // 遍历蛇类中的数组
    for (var i = 1; i < this.snake.arr.length - 1; i++) {
        // 获取坐标系
        var x = this.snake.arr[i].x;
        var y = this.snake.arr[i].y;

        // 渲染背景图片
        this.map.arr[x][y].style.backgroundImage = 'url('+ this.snake.body_img  +')';
    }


    // 获取蛇的头部
    var tail = this.snake.arr[0];
    // 渲染头部图片
    this.map.arr[tail.x][tail.y].style.backgroundImage = 'url('+ this.snake.tail_img[this.snake.tail_idx]  +')';

}


// 游戏开始
Game.prototype.start = function() {
    // 当游戏开始的时候 标记为true
    this.flag = true;
    // 缓存this
    var me = this;
    // 开启定时器
    this.timer = setInterval(function() {
        // 移动
        me.snake.move();
        // 检测是否撞墙
        me.checkMap();
        // 检测是否吃到食物
        me.checkFood();
        // 检测是否吃到自己
        me.checkSnake();
        // 检测是否撞到障碍物
        me.checkBlock();
       
        // 当游戏执行的时候 正常渲染
        if (me.flag) {
            // 清屏
            me.map.clear();
            // 渲染蛇
            me.renderSnake();
            // 渲染食物
            me.renderFood();
            // 渲染障碍物
            me.renderBlock();
        }
       
    }, 200)
}

// 绑定事件
Game.prototype.bindEvent = function() {
    // 缓存this
    var me = this;
    // 为documenet绑定键盘事件
    document.onkeydown = function(e) {
        // 获取对应的编码
        var key = e.keyCode;

        // 判断是否是方向键
        if (key === 37 || key === 38 || key === 39 || key === 40) {
            // 执行蛇转向的方法
            me.snake.change(key);
        }

    }
}


// 结束游戏
Game.prototype.gameOver = function() {
    // 当游戏结束的时候 标记为false
    this.flag = false;
    // 清除定时器
    clearInterval(this.timer);
    // 弹出提示
    alert('游戏结束了');
}


// 边界判断
Game.prototype.checkMap = function() {
    // 获取蛇的头部 （蛇类数组中最后一项）
    var head = this.snake.arr[this.snake.arr.length - 1];

    // 判断
    if (head.x < 0 || head.x > this.map.row - 1 || head.y < 0 || head.y > this.map.col - 1) {
        // 结束游戏
        this.gameOver();
    } 
}


// 重置食物
Game.prototype.resetFood = function() {
    // 定义随机x值
    var x = parseInt(Math.random() * this.map.row);
    // 定义随机y值
    var y = parseInt(Math.random() * this.map.col);

    // 判断食物和蛇的每一节身体的合法性
    for (var i = 0; i < this.snake.arr.length; i++) {
        // 获取一节身体
        var one = this.snake.arr[i];

        // 判断
        if (one.x === x && one.y === y) {
            // 说明重合到了蛇的身上
            // 递归处理
            this.resetFood();
            // 终止执行
            return alert('重合到了蛇的身上');
        }
    }


    // 判断食物和障碍物的每一节身体的合法性
    for (var i = 0; i < this.block.arr.length; i++) {
        // 获取一节身体
        var one = this.block.arr[i];

        // 判断
        if (one.x === x && one.y === y) {
            // 说明重合到了蛇的身上
            // 递归处理
            this.resetFood();
            // 终止执行
            return alert('重合到了障碍物的身上');
        }
    }
    
    // 本质上调用food中重置食物方法
    this.food.resetFood(x, y);
}

// 检测是否吃到食物
Game.prototype.checkFood = function() {
    // 获取蛇头
    var head = this.snake.arr[this.snake.arr.length - 1];

    // 获取食物的坐标
    var x = this.food.x;
    var y = this.food.y;

    // 判断
    if (head.x === x && head.y === y) {
        // 重置食物
        this.resetFood();
        // 执行蛇生长的方法
        this.snake.goUp();
    }
}


// 检测是否吃到自己
Game.prototype.checkSnake = function() {
    // 获取蛇的头部
    var head = this.snake.arr[this.snake.arr.length - 1];

    // 遍历与蛇的每一节身体进行匹配
    for (var i = 0; i < this.snake.arr.length - 1; i++) {
        // 获取一节身体
        var one = this.snake.arr[i];

        // 开始匹配
        if (one.x === head.x && one.y === head.y) {
            // 结束游戏
            this.gameOver();
        }
    }

}

// 定义渲染障碍物方法
Game.prototype.renderBlock = function() {
    // 遍历障碍物数组
    for (var i = 0; i < this.block.arr.length; i++) {
        // 定义变量 简化书写
        var x = this.block.arr[i].x;
        var y = this.block.arr[i].y;

        // 在地图中渲染障碍物
        this.map.arr[x][y].style.backgroundImage = 'url('+ this.block.img_url  +')';
    }
}

// 检测是否撞到障碍物
Game.prototype.checkBlock = function() {
    // 获取蛇的头部
    var head = this.snake.arr[this.snake.arr.length - 1];

    // 遍历
    for (var i = 0; i < this.block.arr.length; i++) {
        // 定义变量 简化书写
        var x = this.block.arr[i].x;
        var y = this.block.arr[i].y;

        if (head.x === x && head.y === y ) {
            // 结束游戏
            this.gameOver();
        }
    } 
}
 